﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections.ObjectModel;
using System.IO;
using SharedLib.DataStructure;

namespace SharedLib.CrossCuttingFramework
{
    /// <summary>
    /// Plugin Manager
    /// </summary>
    public class PluginManager : InterfaceOrganizer
    {

        public PluginManager()
        {
            Initialize();
        }

        /// <summary>
        /// Override for customizd plugin folders
        /// </summary>
        public virtual string GetPluginFolder()
        {
            return "Plugins";
        }

        public IDictionary<string, Type> GetAllPlugins()
        {
            Dictionary<string, Type> rtn = new Dictionary<string, Type>();
            foreach (Type interfaceType in RegisteredClasses.Keys)
            {
                IDictionary<string, Type> classDict = RegisteredClasses[interfaceType];
                foreach (string name in classDict.Keys)
                {
                    if (!rtn.Keys.Contains(name)) rtn.Add(name, classDict[name]);
                }
            }
            return rtn;
        }

        /// <summary>
        /// Override for customizd initialization operations
        /// </summary>
        protected virtual void Initialize()
        {
            RegisterInterface<IPlugin>();
        }

        public virtual void LoadPlugins()
        {
            string folderFullName = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + GetPluginFolder();
            if (!Directory.Exists(folderFullName)) Directory.CreateDirectory(folderFullName);
            foreach (string pluginPath in Directory.GetFiles(folderFullName, "*.dll", System.IO.SearchOption.AllDirectories))
            {
                LoadPlugin(pluginPath);
            }
        }

        /// <summary>
        /// Load plugins from path
        /// </summary>
        /// <param name="fullPath">plugin dir</param>
        public void LoadPlugin(string fullPath)
        {
            Assembly pluginAssembly = Assembly.LoadFile(fullPath);
            foreach (Type pluginType in pluginAssembly.GetTypes())
            {
                foreach (Type typeInterface in pluginType.GetInterfaces())
                {
                    if (typeInterface == typeof(IPlugin))
                    {
                        RegisterClass(pluginType, pluginType.FullName);
                    }
                }
            }
        }


        /// <summary>
        /// Create plugin instance
        /// </summary>
        /// <param name="interfaceName"></param>
        /// <param name="pluginName"></param>
        /// <returns></returns>
        public IPlugin CreatePlugin(string pluginName)
        {
            IDictionary<string, Type> plugins = GetAllPlugins();
            if (plugins.ContainsKey(pluginName))
            {
                Type pluginType = plugins[pluginName];

                return (IPlugin)Activator.CreateInstance(pluginType);
            }
            return null;
        }

        
    }
}
